#include <stdio.h>
#include <stdlib.h>
#include "SuffixTree.h"
#include <time.h>

#define MAX_MOVE 50000  //to move inside file by more than 2GB of bytes

int *currStartPositionsInSufArrayFile; //for the next read, -1 if no more reads
int *buffersLengths;  //the current lengths of the in-memory buffers
int *buffersPointers;    //from 0 to bufferslengths[i]
Suffix **buffers;   //buffers with suffix arrays of partitions - 1 per each partition

extern FILE *suffixArrayFile;
extern char smallSuffixArrayFileNamePrefix[];
//********filled in main
extern int numberOfChunks;
extern int *lengths;

extern int input_buffer_max;
extern int output_buffer_max;

void fillInitialBuffers()
{
	int result;
	int i;
	char currentInputFileName[MAX_PATH_LENGTH];

	//initialize all control structures	
	buffersLengths=(int *)malloc ( sizeof(int)*numberOfChunks);
	buffersPointers=(int *)malloc ( sizeof(int)*numberOfChunks);
	currStartPositionsInSufArrayFile=(int *)malloc ( sizeof(int)*numberOfChunks);
	
	for (i = 0; i < numberOfChunks; i++) 
	{
		buffersLengths[i]=MIN(input_buffer_max,lengths[i]);
		//if(buffersLengths[i]<2)	 //CHECK
		//	buffersLengths[i]=-1;   //CHECK
	}		

	buffers=(Suffix **) malloc ( sizeof(Suffix *)*numberOfChunks);

	if(buffers==NULL)
	{
		printf("Memory error. Cannot allocate memory for input buffers.\n");
		exit(1);
	}

	//1. first read
	if(buffersLengths[0]==-1)
	{
		printf("Input error. No data in the input suffix array.\n");
		exit(2);
	}

	buffers[0]=(Suffix*) malloc ( sizeof(Suffix)*buffersLengths[0]);
	
	sprintf(currentInputFileName,"%s_0", smallSuffixArrayFileNamePrefix);
	if(!(suffixArrayFile=fopen(currentInputFileName,"rb")))
	{
		printf("Cannot open input File %s for reading\n",currentInputFileName);
		exit(1);
	}
	
	result = fread (buffers[0],sizeof(Suffix),buffersLengths[0],suffixArrayFile);

	if ((int)result != buffersLengths[0]) 
	{
	  printf ("Reading into buffer 0 error\n");
	  exit (3);
	}
	
	fclose(suffixArrayFile);

	currStartPositionsInSufArrayFile[0]=buffersLengths[0];
	if(currStartPositionsInSufArrayFile[0]==lengths[0])
	{
		currStartPositionsInSufArrayFile[0]=-1; //entire buffer was loaded, no next read
	}
	buffersPointers[0]=0;

	//2. Fill buffers from 1 to numberOfChunks	
	for(i=1;i<numberOfChunks; i++) 
	{
		if(buffersLengths[i]>=1)  //CHECK
		{
			buffers[i]=(Suffix*) malloc (sizeof(Suffix)*buffersLengths[i]);		
			
			sprintf(currentInputFileName,"%s_%d", smallSuffixArrayFileNamePrefix,i);
			if(!(suffixArrayFile=fopen(currentInputFileName,"rb")))
			{
				printf("Cannot open input File %s for reading\n",currentInputFileName);
				exit(1);
			}
	
			result = fread (buffers[i],sizeof(Suffix),buffersLengths[i],suffixArrayFile);
			if ((int)result != buffersLengths[i]) 
			{
			  printf ("Reading into buffer %d error\n",i);
			  exit (3);
			}

			buffersPointers[i]=0;
			currStartPositionsInSufArrayFile[i]=buffersLengths[i];
			if(currStartPositionsInSufArrayFile[i]>=lengths[i])
			{
				currStartPositionsInSufArrayFile[i]=-1;
			}
			fclose(suffixArrayFile);
		}
		else
		{
			currStartPositionsInSufArrayFile[i]=-1;
			buffersLengths[i]=-1;
			
		}
	}

}

void fseekXXL(FILE *file, int pos)
{
	int currPos=pos;
	while(currPos>MAX_MOVE)
	{
		fseek(file,MAX_MOVE*sizeof(Suffix),SEEK_CUR);
		currPos-=MAX_MOVE;
	}
	fseek(file,currPos*sizeof(Suffix),SEEK_CUR);

}

void refillBuffer(int bufferNumber)
{
	int bufferSize,result;
	char currentInputFileName[MAX_PATH_LENGTH];

	if(currStartPositionsInSufArrayFile[bufferNumber]==-1 || 
		(currStartPositionsInSufArrayFile[bufferNumber])>=lengths[bufferNumber])
	{
		buffersLengths[bufferNumber]=-1; //finished this chunk
		currStartPositionsInSufArrayFile[bufferNumber]=-1;		
		return;
	}

	bufferSize=MIN(lengths[bufferNumber]-(currStartPositionsInSufArrayFile[bufferNumber]),
		input_buffer_max);
	

	buffersLengths[bufferNumber]=bufferSize;
	buffersPointers[bufferNumber]=0;
	
	sprintf(currentInputFileName,"%s_%d", smallSuffixArrayFileNamePrefix,bufferNumber);
	if(!(suffixArrayFile=fopen(currentInputFileName,"rb")))
	{
		printf("Cannot open input File %s for reading\n",currentInputFileName);
		exit(1);
	}

	fseekXXL(suffixArrayFile,currStartPositionsInSufArrayFile[bufferNumber]);
	result=fread (buffers[bufferNumber],sizeof(Suffix),bufferSize,suffixArrayFile);
	if(result!=bufferSize)
	{
		printf("error in refilling buffer %d: wanted to read %d and in fact read %d\n",bufferNumber,bufferSize,result);
		printf("Curr start position in suf array file is %d, buffer size is %d, suffix array file length is %d\n",
			currStartPositionsInSufArrayFile[bufferNumber],bufferSize,lengths[bufferNumber]);
		exit(1);
	}

	fclose(suffixArrayFile);

currStartPositionsInSufArrayFile[bufferNumber]+=bufferSize; //move pointer	
	if(	(currStartPositionsInSufArrayFile[bufferNumber])>=lengths[bufferNumber])
	{
		currStartPositionsInSufArrayFile[bufferNumber]=-1; //no next processing
		
	}

}

